package sk.naive.talker;

import sk.naive.talker.persistence.*;
import sk.naive.talker.props.*;
import sk.naive.talker.server.*;

import java.rmi.RemoteException;
import java.util.*;

/**
 * Location, room.
 *
 * @author <a href="mailto:virgo@naive.deepblue.sk">Richard "Virgo" Richter</a>
 * @author <a href="mailto:rytier@naive.deepblue.sk">Martin "Rytier" Kerni</a>
 * @version $Revision: 1.37 $ $Date: 2007-05-07 10:34:20 $
 */
public class Location implements PersistentObject {
	public static final String LPROP_NAME = "name";
	public static final String LPROP_TOPIC = "topic";
	public static final String LPROP_TOPIC_AUTHOR = "topicAuthor";
	public static final String LPROP_LINKS_OUT = "linksOut";
	public static final String LPROP_VISIBILITY = "visibility";
	public static final String LPROP_OWNERS = "owners";

	private Set<User> users;
	private Set<Location> nearLocations;
	private LocationFinder finder;
	private PersistentPropertyStoreImpl store;

	public Location(Integer id, LocationRegistry locationRegistry) {
		store = new PersistentPropertyStoreImpl(id, locationRegistry.getPropertyConfiguration());
		finder = locationRegistry.finder();
		users = new HashSet<User>();
		nearLocations = new HashSet<Location>();
	}

	/**
	 * Location runtime initialization.
	 * Location must be initialized after all locations are registred at location finder.
	 */
	public void init() {
		Set<Integer> tmpHackedLinksOut = linksOut();
		if (tmpHackedLinksOut == null)
			return;
		for (Integer roomId : linksOut()) {
			nearLocations.add(finder.findLocationById(roomId));
		}
	}

	private Set<Integer> linksOut() {
		Set<Integer> tmpLinksOut = (Set<Integer>) store.get(LPROP_LINKS_OUT);
		if (tmpLinksOut != null) {
			return (Set<Integer>) store.get(LPROP_LINKS_OUT);
		} else {
			return new HashSet<>();
		}
	}

	public Set<Location> nearLocations() {
		return nearLocations;
	}

	public String getName() {
		return (String) get(LPROP_NAME);
	}

	public String description() throws PersistenceException {
		// TODO Toto je des... nahrat v inite
		Iterator<Text> ii = new DbLayer().loadTexts(getId(), TextRelation.LOCATION_DESC, "").iterator();
		if (ii.hasNext()) {
			return (ii.next()).getContent();
		}
		return null;
	}

	public Set<User> users() {
		return users;
	}

	public void userIn(User u) {
		users.add(u);
		finder.userToLocation(u, this);
	}

	public void userOut(User u) {
		users.remove(u);
		finder.userToLocation(u, null);
	}

	public Object get(String key) {
		return store.get(key);
	}

	public void set(String property, Object value) throws PropertyStoreException {
		store.set(property, value);
	}

	public Map<String,Object> getProperties() {
		return store.getProperties();
	}

	public Property getProperty(String key) {
		return store.getProperty(key);
	}

	public String toString() {
		return getName();
	}

	public void addExit(Location to) throws PropertyStoreException, PersistenceException, RemoteException {
		if (!nearLocations.contains(to)) {
			nearLocations.add(to);
			Set<Integer> linksOut = linksOut();
			linksOut.add(to.getId());
			set(LPROP_LINKS_OUT, linksOut);
		}
	}

	public void removeExit(Location to) throws PersistenceException, PropertyStoreException, RemoteException {
		if (nearLocations.contains(to)) {
			nearLocations.remove(to);
			Set<Integer> linksOut = linksOut();
			linksOut.remove(to.getId());
			set(LPROP_LINKS_OUT, linksOut);
		}
	}

	public void addOwner(Integer owner) throws PropertyStoreException {
		Set<Integer> locationOwners = getLocationOwners();
		if (!locationOwners.contains(owner)) {
			locationOwners.add(owner);
			set(LPROP_OWNERS, locationOwners);
		}
	}

	public void removeOwner(Integer owner) throws PropertyStoreException {
		Set<Integer> locationOwners = getLocationOwners();
		if (locationOwners.contains(owner)) {
			locationOwners.remove(owner);
			set(LPROP_OWNERS, locationOwners);
		}
	}

	public Set<Integer> getLocationOwners() {
		Set<Integer> tmpOwners = (Set<Integer>) store.get(LPROP_OWNERS);
		if (tmpOwners != null) {
			return (Set<Integer>) store.get(LPROP_OWNERS);
		} else {
			return new HashSet<Integer>();
		}
	}

	public String getTopic() {
		return (String) getProperties().get(LPROP_TOPIC);
	}

	public Integer getTopicAuthorId() {
		return (Integer) getProperties().get(LPROP_TOPIC_AUTHOR);
	}

	public Integer getId() {
		return store.getId();
	}

	public void setStoredValue(String key, String value) throws PropertyStoreException {
		store.setStoredValue(key, value);
	}
}
